package com.ansion.commonchat.startup.workmanager.bwork.impl.mode;

import static com.ansion.commonchat.startup.workmanager.bwork.BWorkInfo.State.ENQUEUED;

import androidx.annotation.NonNull;
import androidx.arch.core.util.Function;

import com.ansion.commonchat.startup.workmanager.bwork.BData;
import com.ansion.commonchat.startup.workmanager.bwork.BWorkInfo;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;


/**
 * Created by wanghongjie on 2023/5/5
 * Describe : 使用WorkSpecs来描述待执行的Work，是数据缓存中最主要的类
 */
public final class BWorkSpec {

    @NonNull
    public String id;

    @NonNull
    public BWorkInfo.State state = ENQUEUED;

    @NonNull
    public String workerClassName;

    public String inputMergerClassName;

    @NonNull
    public BData input = BData.EMPTY;

    @NonNull
    public BData output = BData.EMPTY;

    public BWorkSpec(@NonNull String id, @NonNull String workerClassName) {
        this.id = id;
        this.workerClassName = workerClassName;
    }

    public BWorkSpec(@NonNull BWorkSpec other) {
        id = other.id;
        workerClassName = other.workerClassName;
        state = other.state;
        inputMergerClassName = other.inputMergerClassName;
        input = new BData(other.input);
        output = new BData(other.output);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        BWorkSpec workSpec = (BWorkSpec) o;
        if (!id.equals(workSpec.id)) return false;
        if (state != workSpec.state) return false;
        if (!workerClassName.equals(workSpec.workerClassName)) return false;
        if (inputMergerClassName != null ? !inputMergerClassName.equals(
                workSpec.inputMergerClassName)
                : workSpec.inputMergerClassName != null) {
            return false;
        }
        if (!input.equals(workSpec.input)) return false;
        return !output.equals(workSpec.output);
    }

    @Override
    public int hashCode() {
        int result = id.hashCode();
        result = 31 * result + state.hashCode();
        result = 31 * result + workerClassName.hashCode();
        result = 31 * result + (inputMergerClassName != null ? inputMergerClassName.hashCode() : 0);
        result = 31 * result + input.hashCode();
        result = 31 * result + output.hashCode();
        return result;
    }

    @NonNull
    @Override
    public String toString() {
        return "{BWorkSpec: " + id + "}";
    }

    public static class IdAndState {

        public String id;

        public BWorkInfo.State state;

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof IdAndState)) return false;

            IdAndState that = (IdAndState) o;

            if (state != that.state) return false;
            return id.equals(that.id);
        }

        @Override
        public int hashCode() {
            int result = id.hashCode();
            result = 31 * result + state.hashCode();
            return result;
        }
    }

    public static class BWorkInfoPojo {

        public String id;

        public BWorkInfo.State state;

        public BData output;

        public List<String> tags;

        @NonNull
        public BWorkInfo toWorkInfo() {
            return new BWorkInfo(
                    UUID.fromString(id),
                    state,
                    output,
                    tags);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof BWorkInfoPojo)) return false;

            BWorkInfoPojo that = (BWorkInfoPojo) o;

            if (id != null ? !id.equals(that.id) : that.id != null) return false;
            if (state != that.state) return false;
            if (output != null ? !output.equals(that.output) : that.output != null) return false;
            return tags != null ? !tags.equals(that.tags) : that.tags != null;
        }

        @Override
        public int hashCode() {
            int result = id != null ? id.hashCode() : 0;
            result = 31 * result + (state != null ? state.hashCode() : 0);
            result = 31 * result + (output != null ? output.hashCode() : 0);
            result = 31 * result + (tags != null ? tags.hashCode() : 0);
            return result;
        }
    }

    public static final Function<List<BWorkInfoPojo>, List<BWorkInfo>> WORK_INFO_MAPPER =
            new Function<List<BWorkInfoPojo>, List<BWorkInfo>>() {
                @Override
                public List<BWorkInfo> apply(List<BWorkInfoPojo> input) {
                    if (input == null) {
                        return null;
                    }
                    List<BWorkInfo> output = new ArrayList<>(input.size());
                    for (BWorkInfoPojo in : input) {
                        output.add(in.toWorkInfo());
                    }
                    return output;
                }
            };
}